<?php

namespace App\Library\FileUpload;

use App\Constant\CacheKey;
use App\Library\HttpClient;
use App\Library\RedisClient;
use Aws\Exception\MultipartUploadException;
use Aws\S3\MultipartUploader;
use Aws\S3\ObjectUploader;
use Aws\S3\S3Client;
use Throwable;

class DogCloudFileUpload
{
    private $handler = null;

    private $accessTokenConfig = [];

    public function __construct()
    {
        $this->accessTokenConfig = $this->getAccessToken();
        $this->handler = $this->getS3Client();
    }

    public function simpleUpload(): array
    {
        try {
//            $this->handler->registerStreamWrapper();
//            $ret =$this->handler->upload(
//                $this->accessTokenConfig["Bucket"],
//                '2023-04-28/644bdc8bbfea5.png',
//                file_get_contents("https://tse4-mm.cn.bing.net/th/id/OIP-C.1TrPg6u4eXkGMR3S0YHzyAHaEo?w=310&h=193&c=7&r=0&o=5&dpr=2&pid=1.7")
//            );
//            $ret = $this->handler->putObject(array(
//                'Bucket'      => $this->accessTokenConfig["Bucket"],
//                'Key'         => '2023-04-28/644bdc8bbfea5.png', // 目标路径
//                'SourceFile'  => file_get_contents('https://e.topthink.com/Uploads/Picture/2023-04-28/644bdc8bbfea5.png'),
//                'ContentType' => '' // 设为空表示让云存储自动设置 MIME 类型
//            ));
//            return $ret->toArray();
            $source = fopen("https://e.topthink.com/Uploads/Picture/2023-04-28/644bdc8bbfea5.png", "rb");
            $uploader = new ObjectUploader(
                $this->handler,
                "s-gz-6629-rabbit-1258813047",//$this->accessTokenConfig["s3Endpoint"],
                '2023-04-28/644bdc8bbfea5.png',
                $source
            );
            do {
                try {
                    $result = $uploader->upload();
                    if ($result["@metadata"]["statusCode"] == '200') {
                        print('文件成功上传');
                    }
                    print($result);
                } catch (MultipartUploadException $e) {
                    rewind($source);
                    $uploader = new MultipartUploader($this->handler, $source, [
                        'state' => $e->getState(),
                    ]);
                }
            } while (!isset($result));
        } catch (Throwable $e) {
            var_dump($e->getMessage());
            return [];
        }
    }

    private function getAccessToken(): array
    {
        $credentials = ["accessKeyId", "secretAccessKey", "sessionToken", "Bucket", "s3Endpoint"];
        $credentials = RedisClient::client()->hMGet(CacheKey::DogCloudAccessToken, $credentials);
        if (empty($credentials["accessKeyId"])) {
            $api = HttpClient::dogeCloudApi('/auth/tmp_token.json', [
                "channel" => "OSS_FULL",
                "scopes"  => ["*"]
            ], true);
            $credentials = ["accessKeyId", "secretAccessKey", "sessionToken", "Bucket", "s3Endpoint"];
            if ($api && $api['code'] == 200) {
                $credentials = $api['data']['Credentials'];
                $setCacheResult = RedisClient::client()->hMSet(CacheKey::DogCloudAccessToken, [
                    "accessKeyId"     => $credentials["accessKeyId"],
                    "secretAccessKey" => $credentials["secretAccessKey"],
                    "sessionToken"    => $credentials,
                    "Bucket"          => $api["data"]["Buckets"][0]["name"],
                    "s3Endpoint"      => $api["data"]["Buckets"][0]["s3Endpoint"]
                ]);
                $setCacheTime = RedisClient::client()->expire(CacheKey::DogCloudAccessToken, 7000);
            }
        }
        return $credentials;
    }

    private function getS3Client(): S3Client
    {
        var_dump($this->accessTokenConfig);
        return new S3Client([
            'region'      => 'automatic',
            'version'     => '2006-03-01',
            'endpoint'    => $this->accessTokenConfig["s3Endpoint"],
            'credentials' => [
                'key'    => $this->accessTokenConfig['accessKeyId'],
                'secret' => $this->accessTokenConfig['secretAccessKey'],
                'token'  => $this->accessTokenConfig['sessionToken']
            ]
        ]);
    }


}
